home *** CD-ROM | disk | FTP | other *** search
/ Java 1996 August / Java - Summer 1996.iso / kaffe-0.2 / kaffe / thread.c < prev    next >
C/C++ Source or Header  |  1996-02-19  |  8KB  |  411 lines

  1. /*
  2.  * thread.c
  3.  * Thread support.
  4.  *
  5.  * Copyright (c) 1996 Systems Architecture Research Centre,
  6.  *           City University, London, UK.
  7.  *
  8.  * See the file "license.terms" for information on usage and redistribution
  9.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  10.  *
  11.  * Written by Tim Wilkinson <tim@sarc.city.ac.uk>, February 1996.
  12.  */
  13.  
  14. #include <assert.h>
  15. #include <string.h>
  16. #include "classMethod.h"
  17. #include "baseClasses.h"
  18. #include "object.h"
  19. #include "thread.h"
  20. #include "locks.h"
  21. #include "md.h"
  22.  
  23. thread* threadQhead[MAX_THREAD_PRIO + 1];
  24. thread* threadQtail[MAX_THREAD_PRIO + 1];
  25. thread* finalman;
  26. thread* gcman;
  27. thread* currentThread;
  28. classes* ThreadClass;
  29. int blockInts;
  30. bool needReschedule;
  31.  
  32. static int talive;
  33. static int tdaemon;
  34.  
  35. extern classes* ClassClass;
  36.  
  37. void reschedule(void);
  38. static void firstStartThread(void);
  39. static thread* startDaemon(void*);
  40. void finaliserMan(void);
  41. void gcMan(void);
  42.  
  43. /*
  44.  * Initialise threads.
  45.  */
  46. void
  47. initThreads(void)
  48. {
  49.     /* Get a handle on the thread class */
  50.     ThreadClass = lookupClass(addString(THREADCLASS));
  51.     assert(ThreadClass != 0);
  52.  
  53.     /* Allocate a thread to be the main thread */
  54.     currentThread = (thread*)alloc_object(ThreadClass, true);
  55.     assert(currentThread != 0);
  56.  
  57.     currentThread->name = 0;
  58.     currentThread->priority = NORM_THREAD_PRIO;
  59.     currentThread->next = 0;
  60.     currentThread->PrivateInfo = THREAD_SUSPENDED;
  61.     currentThread->eetop = (ctx*)malloc(sizeof(ctx));
  62.     assert(currentThread->eetop != 0);
  63.     THREADINFO(currentThread->eetop);
  64.     currentThread->single_step = 0;
  65.     currentThread->daemon = 0;
  66.     currentThread->stillborn = 0;
  67.     currentThread->target = 0;
  68.     currentThread->group = (threadGroup*)execute_java_constructor(0, "java.lang.ThreadGroup", 0, "()V");
  69.     assert(currentThread->group != 0);
  70.  
  71.     talive++;
  72.  
  73.     /* Add thread into runQ */
  74.     resumeThread(currentThread);
  75.  
  76.     /* Start any daemons we need */
  77.     finalman = startDaemon(&finaliserMan);
  78.     gcman = startDaemon(&gcMan);
  79. }
  80.  
  81. /*
  82.  * Start a new thread running.
  83.  */
  84. void
  85. startThread(thread* tid)
  86. {
  87.     /* Allocate a stack context */
  88.     assert(tid->eetop == 0);
  89.     tid->eetop = (ctx*)malloc(sizeof(ctx));
  90.     assert(tid->eetop != 0);
  91.     tid->eetop->stackBase = (void*)malloc(THREADSTACKSIZE);
  92.     assert(tid->eetop->stackBase != 0);
  93.     tid->eetop->stackEnd = tid->eetop->stackBase + THREADSTACKSIZE;
  94.     tid->PrivateInfo = THREAD_SUSPENDED;
  95.  
  96.     /* Construct the initial restore point. */
  97.     THREADINIT(tid->eetop, &firstStartThread);
  98.  
  99.     talive++;
  100.     if (tid->daemon) {
  101.         tdaemon++;
  102.     }
  103.  
  104.     /* Add thread into runQ */
  105.     resumeThread(tid);
  106. }
  107.  
  108. /*
  109.  * All threads start here.
  110.  */
  111. static
  112. void
  113. firstStartThread(void)
  114. {
  115.     /* Every thread starts with the interrupts off */
  116.     intsRestore();
  117.  
  118.     /* Find the run()V method and call it */
  119.     do_execute_java_method(0, currentThread, "run", "()V", 0, 0);
  120.     do_execute_java_method(0, currentThread, "exit", "()V", 0, 0);
  121.     killThread(currentThread);
  122. }
  123.  
  124. /*
  125.  * Resume a thread running.
  126.  */
  127. void
  128. resumeThread(thread* tid)
  129. {
  130.     intsDisable();
  131.  
  132.     if (tid->PrivateInfo != THREAD_RUNNING) {
  133.         tid->PrivateInfo = THREAD_RUNNING;
  134.  
  135.         /* Place thread on the end of its queue */
  136.         if (threadQhead[tid->priority] == 0) {
  137.             threadQhead[tid->priority] = tid;
  138.             threadQtail[tid->priority] = tid;
  139.             if (tid->priority > currentThread->priority) {
  140.                 needReschedule = true;
  141.             }
  142.         }
  143.         else {
  144.             threadQtail[tid->priority]->next = tid;
  145.             threadQtail[tid->priority] = tid;
  146.         }
  147.     }
  148.     intsRestore();
  149. }
  150.  
  151. /*
  152.  * Yield process to another thread of equal priority.
  153.  */
  154. void
  155. yieldThread()
  156. {
  157.     intsDisable();
  158.  
  159.     if (threadQhead[currentThread->priority] != threadQtail[currentThread->priority]) {
  160.  
  161.         /* Get the next thread and move me to the end */
  162.         threadQhead[currentThread->priority] = currentThread->next;
  163.         threadQtail[currentThread->priority]->next = currentThread;
  164.         threadQtail[currentThread->priority] = currentThread;
  165.         currentThread->next = 0;
  166.         needReschedule = true;
  167.     }
  168.  
  169.     intsRestore();
  170. }
  171.  
  172. /*
  173.  * Suspend a thread.
  174.  */
  175. void
  176. suspendThread(thread* tid)
  177. {
  178.     thread** ntid;
  179.  
  180.     intsDisable();
  181.  
  182.     if (tid->PrivateInfo != THREAD_SUSPENDED) {
  183.         tid->PrivateInfo = THREAD_SUSPENDED;
  184.  
  185.         for (ntid = &threadQhead[tid->priority]; *ntid != 0; ntid = &(*ntid)->next) {
  186.             if (*ntid == tid) {
  187.                 *ntid = tid->next;
  188.                 if (tid == currentThread) {
  189.                     reschedule();
  190.                 }
  191.                 break;
  192.             }
  193.         }
  194.     }
  195.  
  196.     intsRestore();
  197. }
  198.  
  199. /*
  200.  * Suspend a thread on a queue.
  201.  */
  202. void
  203. suspendOnQThread(thread* tid, thread** queue)
  204. {
  205.     thread** ntid;
  206.  
  207.     assert(blockInts == 1);
  208.  
  209.     if (tid->PrivateInfo != THREAD_SUSPENDED) {
  210.         tid->PrivateInfo = THREAD_SUSPENDED;
  211.  
  212.         for (ntid = &threadQhead[tid->priority]; *ntid != 0; ntid = &(*ntid)->next) {
  213.             if (*ntid == tid) {
  214.                 *ntid = tid->next;
  215.                 /* Insert onto head of lock wait Q */
  216.                 tid->next = *queue;
  217.                 *queue = tid;
  218.                 if (tid == currentThread) {
  219.                     reschedule();
  220.                 }
  221.                 break;
  222.             }
  223.         }
  224.     }
  225. }
  226.  
  227. /*
  228.  * Kill thread.
  229.  */
  230. void
  231. killThread(thread* tid)
  232. {
  233.     thread** ntid;
  234.  
  235.     intsDisable();
  236.  
  237.     if (tid->PrivateInfo != THREAD_DEAD) {
  238.  
  239.         /* Get thread of runq (if it needs it) */
  240.         if (tid->PrivateInfo == THREAD_RUNNING) {
  241.             for (ntid = &threadQhead[tid->priority]; *ntid != 0; ntid = &(*ntid)->next) {
  242.                 if (*ntid == tid) {
  243.                     *ntid = tid->next;
  244.                     break;
  245.                 }
  246.             }
  247.         }
  248.  
  249.         tid->PrivateInfo = THREAD_DEAD;
  250.         talive--;
  251.         if (tid->daemon) {
  252.             tdaemon--;
  253.         }
  254.  
  255.         /* If we only have daemons left, then everyone is dead. */
  256.         if (talive == tdaemon) {
  257.             /* Am I suppose to close things down nicely ?? */
  258.             exit(0);
  259.         }
  260.  
  261.         /* Thread is garbage collected, don't worry about freeing it. */
  262.  
  263.         /* Run something else */
  264.         needReschedule = true;
  265.     }
  266.     intsRestore();
  267. }
  268.  
  269. /*
  270.  * Change thread priority.
  271.  */
  272. void
  273. setPriorityThread(thread* tid, int prio)
  274. {
  275.     thread** ntid;
  276.  
  277.     if (tid->PrivateInfo == THREAD_SUSPENDED) {
  278.         tid->priority = prio;
  279.         return;
  280.     }
  281.  
  282.     intsDisable();
  283.  
  284.     /* Remove from current thread list */
  285.     for (ntid = &threadQhead[tid->priority]; *ntid != 0; ntid = &(*ntid)->next) {
  286.         if (*ntid == tid) {
  287.             *ntid = tid->next;
  288.             break;
  289.         }
  290.     }
  291.  
  292.     /* Insert onto a new one */
  293.     tid->priority = prio;
  294.     if (threadQhead[prio] == 0) {
  295.         threadQhead[prio] = tid;
  296.         threadQtail[prio] = tid;
  297.         if (prio > currentThread->priority) {
  298.             needReschedule = true;
  299.         }
  300.     }
  301.     else {
  302.         threadQtail[prio]->next = tid;
  303.         threadQtail[prio] = tid;
  304.     }
  305.  
  306.     intsRestore();
  307. }
  308.  
  309. /*
  310.  * Put a thread to sleep.
  311.  */
  312. void
  313. sleepThread(long long time)
  314. {
  315.     abort();
  316. }
  317.  
  318. /*
  319.  * Is this thread alive?
  320.  */
  321. bool
  322. aliveThread(thread* tid)
  323. {
  324.     return (tid->PrivateInfo != THREAD_DEAD ? true : false);
  325. }
  326.  
  327. /*
  328.  * How many stack frames have I invoked?
  329.  */
  330. long
  331. framesThread(thread* tid)
  332. {
  333.     long count;
  334.     THREADFRAMES(tid, count);
  335.     return (count);
  336. }
  337.  
  338. /*
  339.  * Reschedule the thread.
  340.  * Called whenever a change in the running thread is required.
  341.  */
  342. void
  343. reschedule(void)
  344. {
  345.     int i;
  346.     thread* lastThread;
  347.     int b;
  348.  
  349.     /* Check events - we may release a high priority thread */
  350.     checkEvents(false);
  351.  
  352.     for (;;) {
  353.         for (i = MAX_THREAD_PRIO; i >= MIN_THREAD_PRIO; i--) {
  354.             if (threadQhead[i] != 0) {
  355.                 if (threadQhead[i] != currentThread) {
  356.                     b = blockInts;
  357.                     lastThread = currentThread;
  358.                     currentThread = threadQhead[i];
  359.                     THREADSWITCH(currentThread->eetop, lastThread->eetop);
  360.                     blockInts = b;
  361.                 }
  362.                 /* Now we kill the schedule and turn ints
  363.                    back on */
  364.                 needReschedule = false;
  365.                 return;
  366.             }
  367.         }
  368.         /* Nothing to run - wait for external event */
  369.         checkEvents(true);
  370.     }
  371. }
  372.  
  373. /*
  374.  * Start a daemon thread.
  375.  */
  376. static
  377. thread*
  378. startDaemon(void* func)
  379. {
  380.     thread* tid;
  381.  
  382.     tid = (thread*)alloc_object(ThreadClass, true);
  383.     assert(tid != 0);
  384.  
  385.     tid->name = 0;
  386.     tid->priority = MAX_THREAD_PRIO;
  387.     tid->next = 0;
  388.     tid->PrivateInfo = THREAD_SUSPENDED;
  389.     tid->eetop = (ctx*)malloc(sizeof(ctx));
  390.     assert(tid->eetop != 0);
  391.     tid->eetop->stackBase = (void*)malloc(THREADSTACKSIZE);
  392.     assert(tid->eetop->stackBase != 0);
  393.     tid->eetop->stackEnd = tid->eetop->stackBase + THREADSTACKSIZE;
  394.     tid->single_step = 0;
  395.     tid->daemon = 1;
  396.     tid->stillborn = 0;
  397.     tid->target = 0;
  398.     tid->group = 0;
  399.  
  400.     /* Construct the initial restore point. */
  401.     THREADINIT(tid->eetop, func);
  402.  
  403.     talive++;
  404.     tdaemon++;
  405.  
  406.     /* Add thread into runQ */
  407.     resumeThread(tid);
  408.  
  409.     return (tid);
  410. }
  411.